home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / cli / Man3714.lha / Man / Man.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-31  |  26.8 KB  |  1,039 lines

  1. /*
  2. Auto:        sc <file>
  3. */
  4.  
  5. /* $Revision Header built automatically *************** (do not edit) ************
  6. **
  7. ** © Copyright by GuntherSoft
  8. **
  9. ** File             : SnakeSYS:CPrgs/Utils/Man.c
  10. ** Created on       : Friday, 16.07.93 18:00:23
  11. ** Created by       : Kai Iske
  12. ** Current revision : V37.14
  13. **
  14. **
  15. ** Purpose
  16. ** -------
  17. **   - This is a man program, which may scan different directories
  18. **     for man-pages. These directories are set within an ENV-VAR
  19. **     called MANPATHS. Additionally a VIEWER may be set using
  20. **     ENV-VAR MANVIEW (for plain ASCII) or MANVIEWAG (for
  21. **     AMIGAGUIDE). THIS ONE`S PURE AND IN THE PUBLIC DOMAIN
  22. **
  23. ** Revision V37.14
  24. ** --------------
  25. ** created on Donnerstag, 12.01.95 13:30:08  by  Kai Iske.   LogMessage :
  26. **  -*-  changed on Donnerstag, 30.03.95 20:00:01  by  Kai Iske.   LogMessage :
  27. **   - Fixed bug in calling the programs which return a code
  28. **     unequal to zero
  29. **  -*-  created on Donnerstag, 12.01.95 13:30:08  by  Kai Iske.   LogMessage :
  30. **   - Changed version numbering to official scheme
  31. **
  32. ** Revision V1.13
  33. ** --------------
  34. ** created on Monday, 14.11.94 19:40:55  by  Kai Iske.   LogMessage :
  35. **  -*-  changed on Montag, 14.11.94 19:42:42  by  Kai Iske.   LogMessage :
  36. **   - Added new switch "MANLOCAL". This will cause
  37. **     Man to search the current directory before any other
  38. **     (Requested by : Mark Rose)
  39. **  -*-  created on Monday, 14.11.94 19:40:55  by  Kai Iske.   LogMessage :
  40. **   - Added ARexx-Script which allows the usage of Man
  41. **     from within eg. ToolManager.
  42. **     (written by : Franz S. Borgerding)
  43. **
  44. ** Revision V1.12
  45. ** --------------
  46. ** created on Saturday, 12.03.94 15:20:45  by  Kai Iske.   LogMessage :
  47. **  -*-  changed on Sunday, 13.03.94 15:21:31  by  Kai Iske.   LogMessage :
  48. **   - Remove RunCommand() call again. Thanks to Ralph Babel, this
  49. **     change wasn`t needed anymore due to misbehaviour of WShell.
  50. **     (Reported by : Ralph Babel)
  51. **  -*-  created on Saturday, 12.03.94 15:20:45  by  Kai Iske.   LogMessage :
  52. **   - WShell`s incompatibility to SystemTags() forced me to use
  53. **     RunCommand() for launching the external viewer
  54. **     (Suggested/Reported by : Ralph Babel + Ralph Schmidt)
  55. **
  56. ** Revision V1.11
  57. ** --------------
  58. ** created on Monday, 28.02.94 19:33:29  by  Kai Iske.   LogMessage :
  59. **  -*-  changed on Wednesday, 09.03.94 18:44:31  by  Kai Iske.   LogMessage :
  60. **   - Man called AllocVec before the check for OS 37.x was made
  61. **     (Reported by : Ralph Babel)
  62. **  -*-  changed on Saturday, 05.03.94 02:30:54  by  Kai Iske.   LogMessage :
  63. **   - Man produced an enforcer hit when no manpage was supplied
  64. **     (Reported by : Michael van Elst)
  65. **  -*-  changed on Monday, 28.02.94 20:03:34  by  Kai Iske.   LogMessage :
  66. **   - Man will no longer issue an error if you a) didn`t specify a
  67. **     manpage and b) set the MANGETFILE attribute for the File
  68. **     Requester. This way the Requester will popup if you
  69. **     call MAN without any arguments
  70. **     (Requested by : Bill Hogsett)
  71. **  -*-  changed on Monday, 28.02.94 20:02:39  by  Kai Iske.   LogMessage :
  72. **   - The FileRequester will pop up on the default PubScreen now
  73. **     (Requested by : Bill Hogsett)
  74. **   - The default path for the FileRequester will be set to the
  75. **     first Dir of the MANPATHS now
  76. **     (Requested by : Bill Hogsett)
  77. **  -*-  created on Monday, 28.02.94 19:33:29  by  Kai Iske.   LogMessage :
  78. **   - Support for DVI files added
  79. **   - MAN will set the Viewer`s current dir of that where the
  80. **     man page resides in
  81. **
  82. ** Revision V1.10
  83. ** --------------
  84. ** created on Tuesday, 25.01.94 14:41:58  by  Kai Iske.   LogMessage :
  85. **   - Mike Barsoom added MANBASENAME attribute for stripping
  86. **     off any path names from the manpage name. Useful when
  87. **     launching MAN from within (ie) ToolsDaemon
  88. **     (Submitted by : Mike Barsoom)
  89. **
  90. ** Revision V1.9
  91. ** --------------
  92. ** created on Sunday, 23.01.94 21:36:26  by  Kai Iske.   LogMessage :
  93. **   - Recompiled using SAS/C 6.51
  94. **   - Added MANGETFILE parameter
  95. **     (Requested by : Bill Hogsett)
  96. **
  97. ** Revision V1.8
  98. ** --------------
  99. ** created on Saturday, 15.01.94 01:14:17  by  Kai Iske.   LogMessage :
  100. **   - Man now correctly handles multi-assigns, since ExAll
  101. **     doesn`t....;)
  102. **     (Reported by : Jan Hoeydahl)
  103. **
  104. ** Revision V1.7
  105. ** --------------
  106. ** created on Friday, 31.12.93 14:00:28  by  Kai Iske.   LogMessage :
  107. **   - All config variables have been moved to a single one,
  108. **     which will be parsed just like a CommandLine
  109. **     (Suggested by : Michael 'Mick' Hohmann)
  110. **
  111. ** Revision V1.6
  112. ** --------------
  113. ** created on Thursday, 16.12.93 16:49:51  by  Kai Iske.   LogMessage :
  114. **   - Added MANRMEXT, MANAGEXT and MANNOVIEW options,
  115. **     which may be used for extensibility of MAN
  116. **     (Somehow suggested by : Michael 'Mick' Hohmann)
  117. **
  118. ** Revision V1.5
  119. ** --------------
  120. ** created on Thursday, 09.12.93 00:58:47  by  Kai Iske.   LogMessage :
  121. **   - Referenced free memory area
  122. **
  123. ** Revision V1.4
  124. ** --------------
  125. ** created on Wednesday, 08.12.93 22:07:47  by  Kai Iske.   LogMessage :
  126. **  -*-  created on Wednesday, 08.12.93 22:07:47  by  Kai Iske.   LogMessage :
  127. **   - DOS-Library wasn`t closed
  128. **
  129. ** Revision V1.3
  130. ** --------------
  131. ** created on Wednesday, 08.12.93 19:26:17  by  Kai Iske.   LogMessage :
  132. **  -*-  changed on Wednesday, 08.12.93 19:31:23  by  Kai Iske.   LogMessage :
  133. **   - Added CTRL-C checking
  134. **  -*-  created on Wednesday, 08.12.93 19:26:17  by  Kai Iske.   LogMessage :
  135. **   - Recompiled using SAS 6.50
  136. **   - Reduced stack usage
  137. **   - Reduced executable size
  138. **
  139. ** Revision V1.2
  140. ** --------------
  141. ** created on Tuesday, 27.07.93 15:20:51  by  Kai Iske.   LogMessage :
  142. **   - Used MAN as a keyword for the template which prevented MAN
  143. **     to accept inputs like "man man".
  144. **
  145. ** Revision V1.1
  146. ** --------------
  147. ** created on Monday, 26.07.93 17:42:32  by  Kai Iske.   LogMessage :
  148. **   - Accidentially called Exit() instead of exit(), which
  149. **     prevented the program to pass the cleanup code of SAS.
  150. **     So a lock to the directory was kept and the shell could
  151. **     never been left.............
  152. **
  153. ** Revision V1.0
  154. ** --------------
  155. ** created on Friday, 16.07.93 18:00:23  by  Kai Iske.   LogMessage :
  156. **  -*-  changed on Saturday, 17.07.93 16:30:41  by  Kai Iske.   LogMessage :
  157. **   - Man now searches for files that end up with .doc/.man/.guide
  158. **     If a .guide file is found, the second Viewer (MANVIEWAG)
  159. **     will be used to display the AmigaGuide viewer. Otherwise
  160. **     the normal viewer (MANVIEW) will be used
  161. **  -*-  created on Friday, 16.07.93 18:00:23  by  Kai Iske.   LogMessage :
  162. **     --- Initial release ---
  163. **
  164. *********************************************************************************/
  165. #define REVISION "37.14"
  166. #define REVDATE  "30.03.95"
  167. #define REVTIME  "20:00:01"
  168. #define AUTHOR   "Kai Iske"
  169. #define VERNUM   37
  170. #define REVNUM   14
  171.  
  172.  
  173.  
  174. #define        _USE_SYSBASE
  175.  
  176.  
  177.  
  178. /**********************************************************************/
  179. /*         This is, so that the code references our Libraries         */
  180. /*                      stored in our structure                       */
  181. /**********************************************************************/
  182. #define        DOSBase        MC->mc_DOSBase
  183. #define        UtilityBase    MC->mc_UtilityBase
  184.  
  185.  
  186. #include    <string.h>
  187. #include    <stdlib.h>
  188. #include    <exec/types.h>
  189. #include    <exec/memory.h>
  190. #include    <exec/execbase.h>
  191. #include    <libraries/asl.h>
  192. #include    <dos/dos.h>
  193. #include    <dos/exall.h>
  194. #include    <dos/dostags.h>
  195. #include    <proto/exec.h>
  196. #include    <proto/asl.h>
  197. #include    <clib/dos_protos.h>
  198. #include    <clib/utility_protos.h>
  199. #include    <pragmas/dos_pragmas.h>
  200. #include    <pragmas/utility_pragmas.h>
  201.  
  202.  
  203.  
  204.  
  205. /**********************************************************************/
  206. /*             This is the private structure for all vars             */
  207. /**********************************************************************/
  208. struct ManControl
  209. {
  210.     struct    DOSLibrary    *mc_DOSBase;
  211.     struct    Library        *mc_UtilityBase;
  212.     struct    ExAllControl    *mc_EAC;
  213.     char            mc_ManOpt[2050],
  214.                 mc_ManPaths[1026],
  215.                 mc_ViewCmd[1026],
  216.                 mc_ViewCmdAG[1026],
  217.                 mc_ViewCmdDVI[1026],
  218.                 mc_CheckDir[1026],
  219.                 mc_SearchName[2050],
  220.                 mc_FileName[1026],
  221.                 mc_Pattern[3076],
  222.                 mc_NormExt[1026],
  223.                 mc_AGExt[1026],
  224.                 mc_DVIExt[1026],
  225.                 mc_NameBuffer[1026],
  226.                 mc_NonExt[1026];
  227.     APTR            *mc_EAB;
  228.     BPTR            mc_OutHandle;
  229.     BOOL            mc_Found,
  230.                 mc_Breaked;
  231. };
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238. /**********************************************************************/
  239. /*                             Prototypes                             */
  240. /**********************************************************************/
  241. static char    *GetDir(char *NewName, char *OldName);
  242. static void    DoCheckDir(struct ManControl *MC);
  243. static BOOL    IsAssign(struct ManControl *MC);
  244. static void    DetermineFileType(struct ManControl *MC);
  245.  
  246.  
  247.  
  248.  
  249.  
  250. /**********************************************************************/
  251. /*                           Version-String                           */
  252. /**********************************************************************/
  253. static const char *Version    = "$VER: Man "REVISION" ("REVDATE")\0";
  254.  
  255.  
  256.  
  257.  
  258. /**********************************************************************/
  259. /*                 Template for Command-Line parsing                  */
  260. /**********************************************************************/
  261. static const char *Template    = "MANPAGE";
  262. enum {MAN_ARG, TMP_LAST_ARG};
  263.  
  264.  
  265.  
  266.  
  267. /**********************************************************************/
  268. /*                    Template for MANOPT settings                    */
  269. /**********************************************************************/
  270. static const char *ManTemplate    = "MANPATHS/K/A,MANVIEW/K/A,MANVIEWAG/K/A,MANVIEWDVI/K/A,MANNRMEXT/K,MANAGEXT/K,MANDVIEXT/K,MANNOVIEW/K,MANGETFILE/S,MANBASENAME/S,MANLOCAL/S";
  271. enum {MANPATHS_ARG, MANVIEW_ARG, MANVIEWAG_ARG, MANVIEWDVI_ARG, MANNRMEXT_ARG, MANAGEXT_ARG, MANDVIEXT_ARG, MANNOVIEW_ARG, MANGETFILE_ARG, MANBASENAME_ARG, MANLOCAL_ARG, MAN_LAST_ARG};
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278. /**********************************************************************/
  279. /*                       This is the main part                        */
  280. /**********************************************************************/
  281. ULONG __saveds main(void)
  282. {
  283.     struct    ManControl    *MC;
  284.     struct    Process        *MyProc;
  285.     struct    RDArgs        *RDArgs,
  286.                 *ManRDArgs;
  287.     APTR            *Args,
  288.                 *ManArgs;
  289.     ULONG            MySig;
  290.     char            *DirOffset;
  291.     BOOL            StartedSearch    = FALSE,
  292.                 UseAsl        = FALSE,
  293.                 CheckLocal    = FALSE,
  294.                 GotManPage;
  295.  
  296.  
  297.         // Allocate control structure
  298.  
  299.     if(!(MC = AllocMem(sizeof(struct ManControl), MEMF_CLEAR)))
  300.         return(20);
  301.  
  302.     MC->mc_Found        = FALSE;
  303.     MC->mc_Breaked        = FALSE;
  304.  
  305.  
  306.         // Don`t start from WB
  307.  
  308.     MyProc    = (struct Process *)FindTask(NULL);
  309.  
  310.     if(!MyProc->pr_CLI)
  311.     {
  312.         struct    WBStartup    *Msg;
  313.  
  314.         WaitPort(&MyProc->pr_MsgPort);
  315.         Msg    = (struct WBStartup *)GetMsg(&MyProc->pr_MsgPort);
  316.  
  317.         Disable();
  318.         ReplyMsg((struct Message *)Msg);
  319.         FreeMem(MC, sizeof(struct ManControl));
  320.  
  321.         return(0);
  322.     }
  323.  
  324.  
  325.         // Try to open DOSBase
  326.  
  327.     if(!(DOSBase    = (struct DOSLibrary *)OpenLibrary("dos.library", 0)))
  328.     {
  329.         FreeMem(MC, sizeof(struct ManControl));
  330.         return(20);
  331.     }
  332.  
  333.  
  334.         // Get Out Handle
  335.  
  336.     MC->mc_OutHandle = Output();
  337.  
  338.  
  339.  
  340.         // Check for System we`re running on
  341.  
  342.     if(((struct Library *)*((ULONG **)0x4L))->lib_Version < 37)
  343.     {
  344.         Write(MC->mc_OutHandle, "You must use KickStart 2.04 (37.175) or higher for MAN\n", 55);
  345.  
  346.             // Close library
  347.  
  348.         CloseLibrary((struct Library *)DOSBase);
  349.             // Free buffer
  350.  
  351.         FreeMem(MC, sizeof(struct ManControl));
  352.         return(20);
  353.     }
  354.  
  355.  
  356.         // Try to open UtilityBase
  357.  
  358.     if(!(UtilityBase = OpenLibrary("utility.library", 0)))
  359.     {
  360.         CloseLibrary((struct Library *)DOSBase);
  361.         FreeMem(MC, sizeof(struct ManControl));
  362.         return(20);
  363.     }
  364.  
  365.  
  366.         // Get buffer for Commandline parsing
  367.  
  368.     if((Args = AllocVec(TMP_LAST_ARG * sizeof(ULONG), MEMF_CLEAR)))
  369.     {
  370.             // Get buffer for MANOPT parsing
  371.  
  372.         if((ManArgs = AllocVec(MAN_LAST_ARG * sizeof(ULONG), MEMF_CLEAR)))
  373.         {
  374.                 // Get RDArgs structure for MANOPT parsing
  375.  
  376.             if((ManRDArgs = AllocDosObject(DOS_RDARGS, NULL)))
  377.             {
  378.                     // Get structure for ExAll()
  379.  
  380.                 if((MC->mc_EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  381.                 {
  382.                         // Get buffer for ExAll()
  383.  
  384.                     if((MC->mc_EAB = AllocVec(sizeof(struct ExAllData)*20, MEMF_CLEAR)))
  385.                     {
  386.                             // Try to parse commandline
  387.  
  388.                         if((RDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL)))
  389.                         {
  390.                                 // Rearrange pointer to paths
  391.  
  392.                             DirOffset    = MC->mc_ManPaths;
  393.  
  394.                                 // Did we get a manpage ?!?
  395.  
  396.                             GotManPage    = (BOOL)(Args[MAN_ARG] != NULL);
  397.  
  398.  
  399.                                 // Try to get MANOPT Env-Variable
  400.  
  401.                             if(GetVar("MANOPT", MC->mc_ManOpt, 2048, GVF_GLOBAL_ONLY) >= 1)
  402.                             {
  403.                                     // Try to parse strings
  404.  
  405.                                 strcat(MC->mc_ManOpt, "\n");
  406.                                 ManRDArgs->RDA_Source.CS_Buffer    = MC->mc_ManOpt;
  407.                                 ManRDArgs->RDA_Source.CS_Length    = strlen(MC->mc_ManOpt);
  408.                                 ManRDArgs->RDA_Source.CS_CurChr    = 0;
  409.                                 ManRDArgs->RDA_DAList        = NULL;
  410.                                 ManRDArgs->RDA_Buffer        = NULL;
  411.                                 ManRDArgs->RDA_BufSiz        = 0;
  412.                                 ManRDArgs->RDA_ExtHelp        = NULL;
  413.                                 ManRDArgs->RDA_Flags        = 0;
  414.  
  415.                                     // Try to parse MANOPT variable
  416.  
  417.                                 if(ReadArgs((char *)ManTemplate, (LONG *)ManArgs, ManRDArgs))
  418.                                 {
  419.                                         // Get Paths etc.pp
  420.  
  421.                                     strcpy(MC->mc_ManPaths, (char *)ManArgs[MANPATHS_ARG]);
  422.                                     strcpy(MC->mc_ViewCmd, (char *)ManArgs[MANVIEW_ARG]);
  423.                                     strcpy(MC->mc_ViewCmdAG, (char *)ManArgs[MANVIEWAG_ARG]);
  424.                                     strcpy(MC->mc_ViewCmdDVI, (char *)ManArgs[MANVIEWDVI_ARG]);
  425.  
  426.                                         // Per default use the ASCII viewer for "non-extension" files
  427.  
  428.                                     strcpy(MC->mc_NonExt, MC->mc_ViewCmd);
  429.  
  430.                                         // Get additional patterns for normal texts
  431.  
  432.                                     if(ManArgs[MANNRMEXT_ARG])
  433.                                         strcpy(MC->mc_NormExt, (char *)ManArgs[MANNRMEXT_ARG]);
  434.  
  435.                                         // Get additional patterns for AmigaGuide texts
  436.  
  437.                                     if(ManArgs[MANAGEXT_ARG])
  438.                                         strcpy(MC->mc_AGExt, (char *)ManArgs[MANAGEXT_ARG]);
  439.  
  440.                                         // Get additional patterns for DVI files
  441.  
  442.                                     if(ManArgs[MANDVIEXT_ARG])
  443.                                         strcpy(MC->mc_DVIExt, (char *)ManArgs[MANDVIEXT_ARG]);
  444.  
  445.                                         // Get name of viewer to use when no extension was found
  446.  
  447.                                     if(ManArgs[MANNOVIEW_ARG])
  448.                                         strcpy(MC->mc_NonExt, (char *)ManArgs[MANNOVIEW_ARG]);
  449.  
  450.                                         // Check for GetFile attribute
  451.  
  452.                                     if(ManArgs[MANGETFILE_ARG])
  453.                                         UseAsl        = TRUE;
  454.  
  455.                                         // Check for CheckLocal attribute
  456.  
  457.                                     if(ManArgs[MANLOCAL_ARG])
  458.                                         CheckLocal    = TRUE;
  459.  
  460.                                         // Do we have a manpage ???
  461.  
  462.                                     if(GotManPage)
  463.                                     {
  464.                                             // Set pattern for ExAll() search
  465.  
  466.                                         if(ManArgs[MANBASENAME_ARG])
  467.                                             strcpy(MC->mc_SearchName, (char *)FilePart(Args[MAN_ARG]));
  468.                                         else
  469.                                             strcpy(MC->mc_SearchName, Args[MAN_ARG]);
  470.  
  471.                                             // Append patterns
  472.  
  473.                                         strcat(MC->mc_SearchName, "(.doc|.man|.guide|.dvi|");
  474.                                         strcat(MC->mc_SearchName, MC->mc_NormExt);
  475.                                         strcat(MC->mc_SearchName, "|");
  476.                                         strcat(MC->mc_SearchName, MC->mc_AGExt);
  477.                                         strcat(MC->mc_SearchName, "|");
  478.                                         strcat(MC->mc_SearchName, MC->mc_DVIExt);
  479.                                         strcat(MC->mc_SearchName, "|)");
  480.  
  481.                                             // Parse the pattern
  482.  
  483.                                         if(ParsePatternNoCase(MC->mc_SearchName, MC->mc_Pattern, 1024) != -1)
  484.                                         {
  485.                                                 // Ok, reached this point
  486.  
  487.                                             StartedSearch    = TRUE;
  488.  
  489.                                                 // Loop for all dirs and wait until file has been found
  490.  
  491.                                             while(!MC->mc_Found && !MC->mc_Breaked && DirOffset)
  492.                                             {
  493.                                                     // Check for CTRL-C
  494.  
  495.                                                 MySig    = CheckSignal(SIGBREAKF_CTRL_C);
  496.  
  497.                                                 if(!(MySig & SIGBREAKF_CTRL_C))
  498.                                                 {
  499.                                                         // Check currentdir first?
  500.  
  501.                                                     if(CheckLocal)
  502.                                                     {
  503.                                                         MC->mc_CheckDir[0]    = 0;
  504.                                                         CheckLocal        = FALSE;
  505.                                                     }
  506.                                                     else
  507.                                                     {
  508.                                                             // Extract next directory from list
  509.  
  510.                                                         DirOffset = GetDir(MC->mc_CheckDir, DirOffset);
  511.                                                     }
  512.  
  513.                                                         // This dir an assign ???
  514.  
  515.                                                     if(IsAssign(MC))
  516.                                                     {
  517.                                                         struct    MsgPort    *OldSysTask;
  518.                                                         struct    DevProc    *DirProc    = NULL;
  519.                                                         BOOL    ErrLoop            = FALSE;
  520.  
  521.                                                             // Get old FileSystemTask
  522.  
  523.                                                         OldSysTask    = GetFileSysTask();
  524.  
  525.                                                             // Loop for dirs assigned
  526.  
  527.                                                         do
  528.                                                         {
  529.                                                                 // get the deviceproc for this Assign
  530.  
  531.                                                             if((DirProc = GetDeviceProc(MC->mc_CheckDir, DirProc)))
  532.                                                             {
  533.                                                                     // Set FileSystem task for locking
  534.  
  535.                                                                 SetFileSysTask(DirProc->dvp_Port);
  536.  
  537.                                                                     // Get full device/path name and try to scan dir
  538.  
  539.                                                                 if(NameFromLock(DirProc->dvp_Lock, MC->mc_NameBuffer, 1024) == DOSTRUE)
  540.                                                                     DoCheckDir(MC);
  541.                                                                 else
  542.                                                                 {
  543.                                                                     PrintFault(IoErr(), "Man ");
  544.                                                                     ErrLoop    = TRUE;
  545.                                                                 }
  546.                                                             }
  547.                                                             else
  548.                                                             {
  549.                                                                 ULONG    Err = IoErr();
  550.  
  551.                                                                 if(Err != ERROR_NO_MORE_ENTRIES)
  552.                                                                 {
  553.                                                                     PrintFault(IoErr(), "Man ");
  554.                                                                     ErrLoop    = TRUE;
  555.                                                                 }
  556.                                                             }
  557.  
  558.                                                             // Loop for additional assignments
  559.  
  560.                                                         } while(!ErrLoop && !MC->mc_Found && !MC->mc_Breaked && DirProc && (DirProc->dvp_Flags & DVPF_ASSIGN));
  561.  
  562.                                                             // Restore old FileSystemTask
  563.  
  564.                                                         SetFileSysTask(OldSysTask);
  565.  
  566.                                                             // Still having a DeviceProc ??? -> Release it
  567.  
  568.                                                         if(DirProc)
  569.                                                             FreeDeviceProc(DirProc);
  570.  
  571.                                                             // Error occured -> End whole loop
  572.  
  573.                                                         if(ErrLoop)
  574.                                                             DirOffset = NULL;
  575.                                                     }
  576.                                                     else
  577.                                                     {
  578.                                                             // For "normal" dirs simply check
  579.  
  580.                                                         strcpy(MC->mc_NameBuffer, MC->mc_CheckDir);
  581.  
  582.                                                         DoCheckDir(MC);
  583.                                                     }
  584.                                                 }
  585.                                                 else
  586.                                                     MC->mc_Breaked = TRUE;
  587.                                             }
  588.  
  589.                                             if(!MC->mc_Found)
  590.                                                 strcpy(MC->mc_FileName, Args[MAN_ARG]);
  591.                                         }
  592.                                         else
  593.                                             PrintFault(IoErr(), "Man ");
  594.                                     }
  595.                                     else
  596.                                     {
  597.                                             // if no popup wanted, issue error
  598.  
  599.                                         if(!UseAsl)
  600.                                             PrintFault(ERROR_REQUIRED_ARG_MISSING, "Man ");
  601.                                     }
  602.  
  603.                                     FreeArgs(ManRDArgs);
  604.                                 }
  605.                                 else
  606.                                     PrintFault(IoErr(), "Man (MANOPT) ");
  607.                             }
  608.                             else
  609.                                 PrintFault(IoErr(), "Man (MANOPT) ");
  610.  
  611.                             FreeArgs(RDArgs);
  612.                         }
  613.                         else
  614.                             PrintFault(IoErr(), "Man ");
  615.  
  616.                         FreeVec(MC->mc_EAB);
  617.                     }
  618.                     else
  619.                         FPuts(MC->mc_OutHandle, "Man : Could not allocate buffer for ExAll()\n");
  620.  
  621.                     FreeDosObject(DOS_EXALLCONTROL, (void *)MC->mc_EAC);
  622.                 }
  623.                 else
  624.                     FPuts(MC->mc_OutHandle, "Man : Could not allocate structure for ExAll()\n");
  625.  
  626.                 FreeDosObject(DOS_RDARGS, (void *)ManRDArgs);
  627.             }
  628.             else
  629.                 FPuts(MC->mc_OutHandle, "Man : Could not allocate structure for MANOPT parsing\n");
  630.  
  631.             FreeVec(ManArgs);
  632.         }
  633.         else
  634.             FPuts(MC->mc_OutHandle, "Man : Could not allocate buffer for MANOPT parsing\n");
  635.  
  636.         FreeVec(Args);
  637.     }
  638.     else
  639.         FPuts(MC->mc_OutHandle, "Could not allocate buffer for CommandLine Parsing\n");
  640.  
  641.  
  642.         // Found and not breaked ???
  643.  
  644.     if((MC->mc_Found || UseAsl) && !MC->mc_Breaked)
  645.     {
  646.         if(!MC->mc_Found && UseAsl)
  647.         {
  648.             struct    Library        *AslBase;
  649.             struct    FileRequester    *FileReq;
  650.  
  651.                 // Open ASL library
  652.  
  653.             if((AslBase = OpenLibrary("asl.library", 37)))
  654.             {
  655.                     // Extract first path of MANPATH
  656.  
  657.                 GetDir(MC->mc_CheckDir, MC->mc_ManPaths);
  658.  
  659.                     // Create FileRequester
  660.  
  661.                 if((FileReq = AllocAslRequestTags(ASL_FileRequest,
  662.                     ASLFR_PubScreenName,    NULL,
  663.                     ASLFR_PositiveText,    "Show",
  664.                     ASLFR_Flags2,        FRF_REJECTICONS,
  665.                     ASLFR_RejectIcons,    TRUE,
  666.                     ASLFR_TitleText,    "Man page not found; please select",
  667.                     ASLFR_InitialFile,    MC->mc_FileName,
  668.                     ASLFR_InitialDrawer,    MC->mc_CheckDir,
  669.                 TAG_DONE)))
  670.                 {
  671.                         // Let the user select
  672.  
  673.                     if(AslRequest(FileReq, TAG_DONE))
  674.                     {
  675.                             // Copy Drawer part
  676.  
  677.                         strcpy(MC->mc_CheckDir, FileReq->fr_Drawer);
  678.  
  679.                             // ...and file part
  680.  
  681.                         strcpy(MC->mc_FileName, FileReq->fr_File);
  682.  
  683.                             // Check for type of file to be displayed
  684.  
  685.                         DetermineFileType(MC);
  686.                     }
  687.  
  688.                         // Free FileRequester
  689.  
  690.                     FreeAslRequest(FileReq);
  691.                 }
  692.                 else
  693.                     PrintFault(ERROR_NO_FREE_STORE, "Man (FileRequester) ");
  694.  
  695.                     // Close library again
  696.  
  697.                 CloseLibrary(AslBase);
  698.             }
  699.             else
  700.                 PrintFault(ERROR_NO_FREE_STORE, "Man (FileRequester) ");
  701.         }
  702.  
  703.             // Really found a man page ???
  704.  
  705.         if(MC->mc_Found)
  706.         {
  707.             char    *Offset    = PathPart(MC->mc_CheckDir);
  708.             BPTR    CurDir;
  709.  
  710.  
  711.                 // Get name of path doc file resides in
  712.  
  713.             memset(MC->mc_FileName, 0, 1024);
  714.             strncpy(MC->mc_FileName, MC->mc_CheckDir, (ULONG)(Offset - MC->mc_CheckDir));
  715.  
  716.                 // And try to lock directory
  717.  
  718.             CurDir    = Lock(MC->mc_FileName, ACCESS_READ);
  719.  
  720.                 // Load in viewer
  721.  
  722.             if(SystemTags(MC->mc_SearchName,
  723.                 NP_CurrentDir,    CurDir,
  724.                 NP_StackSize,    8192,
  725.             TAG_DONE) == -1)
  726.             {
  727.                     // Free lock on current dir, if command could not be launched
  728.  
  729.                 UnLock(CurDir);
  730.             }
  731.         }
  732.  
  733.  
  734.                 // Close libs
  735.  
  736.         CloseLibrary((struct Library *)DOSBase);
  737.         CloseLibrary(UtilityBase);
  738.  
  739.             // Free structure
  740.  
  741.         FreeMem(MC, sizeof(struct ManControl));
  742.         return(0);
  743.     }
  744.         // Got buffers ???
  745.  
  746.     else if(Args && RDArgs)
  747.     {
  748.             // Started search ???
  749.  
  750.         if(StartedSearch)
  751.         {
  752.                 // Not breaked ???
  753.  
  754.             if(!MC->mc_Breaked)
  755.             {
  756.                     // No pages found
  757.  
  758.                 FPuts(MC->mc_OutHandle, "Man-Pages not found for : ");
  759.                 FPuts(MC->mc_OutHandle, MC->mc_FileName);
  760.                 FPuts(MC->mc_OutHandle, "\n");
  761.             }
  762.             else
  763.                 FPuts(MC->mc_OutHandle, "Man : ^C...\n");
  764.         }
  765.  
  766.             // Close libs
  767.  
  768.         CloseLibrary((struct Library *)DOSBase);
  769.         CloseLibrary(UtilityBase);
  770.  
  771.             // Free structure
  772.  
  773.         FreeMem(MC, sizeof(struct ManControl));
  774.         return(10);
  775.     }
  776.  
  777.         // Close libs
  778.  
  779.     CloseLibrary((struct Library *)DOSBase);
  780.     CloseLibrary(UtilityBase);
  781.  
  782.         // Free structure
  783.  
  784.     FreeMem(MC, sizeof(struct ManControl));
  785.     return(20);
  786. }
  787.  
  788.  
  789.  
  790.  
  791.  
  792. /**********************************************************************/
  793. /*          Get portions from the Env-Var -> Next directory           */
  794. /**********************************************************************/
  795. static char *GetDir(char *NewDir, char *OldDir)
  796. {
  797.     while(*OldDir == ' ')
  798.         OldDir++;
  799.  
  800.     while((*OldDir != '\n') && (*OldDir != '\0') && (*OldDir != '|') && (*OldDir != ','))
  801.         *NewDir++ = *OldDir++;
  802.  
  803.     *NewDir        = '\0';
  804.  
  805.     if(*OldDir == '\n' || *OldDir == '\0')
  806.         OldDir = NULL;
  807.     else
  808.         OldDir++;
  809.  
  810.     return(OldDir);
  811. }
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820. /**********************************************************************/
  821. /*                        Check this directory                        */
  822. /**********************************************************************/
  823. static void DoCheckDir(struct ManControl *MC)
  824. {
  825.     BPTR    TestLock;
  826.     ULONG    MySig;
  827.     BOOL    GoOn;
  828.  
  829.         // Try to lock directory
  830.  
  831.     if((TestLock = Lock(MC->mc_NameBuffer, SHARED_LOCK)))
  832.     {
  833.             // Fill in ExAll structure
  834.  
  835.         MC->mc_EAC->eac_LastKey        = 0;
  836.         MC->mc_EAC->eac_MatchString    = MC->mc_Pattern;
  837.         MC->mc_EAC->eac_MatchFunc    = NULL;
  838.  
  839.         do
  840.         {
  841.                 // Check for CTRL-C
  842.  
  843.             MySig = CheckSignal(SIGBREAKF_CTRL_C);
  844.             if((MySig & SIGBREAKF_CTRL_C))
  845.                 MC->mc_Breaked = TRUE;
  846.  
  847.                 // Do the scanning
  848.  
  849.             GoOn = ExAll(TestLock, (struct ExAllData *)MC->mc_EAB, (20*sizeof(struct ExAllData)), ED_NAME, MC->mc_EAC);
  850.  
  851.                 // Error occured ???
  852.  
  853.             if((!GoOn) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  854.                 PrintFault(IoErr(), "Man ");
  855.  
  856.                 // End of dir reached ;
  857.  
  858.             if(MC->mc_EAC->eac_Entries == 0)
  859.                 GoOn = FALSE;
  860.             else if(!MC->mc_Breaked)
  861.             {
  862.                     // Copy real name of directory to our CheckDir buffer
  863.  
  864.                 strcpy(MC->mc_CheckDir, MC->mc_NameBuffer);
  865.  
  866.                     // Get first name matching
  867.  
  868.                 strcpy(MC->mc_FileName, ((struct ExAllData *)MC->mc_EAB)->ed_Name);
  869.  
  870.  
  871.                     // Check for type of file and set command
  872.  
  873.                 DetermineFileType(MC);
  874.             }
  875.         } while(GoOn);
  876.  
  877.             // Unlock Directory
  878.  
  879.         UnLock(TestLock);
  880.     }
  881.     else
  882.     {
  883.             // Display message
  884.  
  885.         FPuts(MC->mc_OutHandle, "Man : Skipping directory; not existent : ");
  886.         FPuts(MC->mc_OutHandle, MC->mc_CheckDir);
  887.         FPuts(MC->mc_OutHandle, "\n");
  888.     }
  889. }
  890.  
  891.  
  892.  
  893. /**********************************************************************/
  894. /*                 Check if a given name is an assign                 */
  895. /**********************************************************************/
  896. static BOOL IsAssign(struct ManControl *MC)
  897. {
  898.     struct    DosList    *DList;
  899.     UBYTE        *AssignName;
  900.     UCOUNT        AssignLength;
  901.     LONG        Position;
  902.     BOOL        RetVal    = FALSE;
  903.  
  904.     if(!strlen(MC->mc_CheckDir))
  905.         return(FALSE);
  906.  
  907.     Position = SplitName(MC->mc_CheckDir, ':', MC->mc_NameBuffer, 0, 1024);
  908.  
  909.     if(Position != -1)
  910.     {
  911.         if(MC->mc_CheckDir[Position] == '\0')
  912.         {
  913.             if((DList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ)) > (struct DosList *)1)
  914.             {
  915.                 while(DList = NextDosEntry(DList, LDF_ASSIGNS))
  916.                 {
  917.                     AssignName    = (UBYTE *)BADDR(DList->dol_Name);
  918.                     AssignLength    = AssignName[0];
  919.  
  920.                     if(!Strnicmp(AssignName + 1, MC->mc_NameBuffer, AssignLength))
  921.                     {
  922.                         RetVal = TRUE;
  923.                         break;
  924.                     }
  925.                 }
  926.  
  927.                 UnLockDosList(LDF_ASSIGNS | LDF_READ);
  928.             }
  929.         }
  930.     }
  931.  
  932.     return(RetVal);
  933. }
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941. /**********************************************************************/
  942. /*       Check for the file given and set command to be called        */
  943. /**********************************************************************/
  944. static void DetermineFileType(struct ManControl *MC)
  945. {
  946.         // Check extension to decide whether it`s an AmigaGuide file
  947.  
  948.     if(strchr(MC->mc_FileName, '.'))
  949.     {
  950.         char    *ExtPtr,
  951.             *DelPtr;
  952.         int    ExtLen;
  953.         BOOL    FoundAG        = FALSE,
  954.             FoundDVI    = FALSE;
  955.  
  956.             // Append default .guide extension and additional
  957.             // seperator for ease of calculating the length
  958.  
  959.         ExtPtr    = MC->mc_AGExt;
  960.         strcat(ExtPtr, "|.guide|");
  961.  
  962.             // Loop for all extensions
  963.  
  964.         while(!FoundAG && (ExtPtr = strchr(ExtPtr, '.')))
  965.         {
  966.                 // Calc len of extension
  967.  
  968.             DelPtr    = strchr(ExtPtr, '|');
  969.             ExtLen    = DelPtr - ExtPtr;
  970.  
  971.             if(!strnicmp(&MC->mc_FileName[strlen(MC->mc_FileName) - ExtLen], ExtPtr, ExtLen))
  972.                 FoundAG    = TRUE;
  973.  
  974.             ExtPtr++;
  975.         }
  976.  
  977.             // Now set view command accordingly
  978.  
  979.         if(FoundAG)
  980.             strcpy(MC->mc_SearchName, MC->mc_ViewCmdAG);
  981.         else
  982.         {
  983.                 // No AmigaGuide file found, check for DVI
  984.  
  985.                 // Append default .guide extension and additional
  986.                 // seperator for ease of calculating the length
  987.  
  988.             ExtPtr    = MC->mc_DVIExt;
  989.             strcat(ExtPtr, "|.dvi|");
  990.  
  991.                 // Loop for all extensions
  992.  
  993.             while(!FoundDVI && (ExtPtr = strchr(ExtPtr, '.')))
  994.             {
  995.                     // Calc len of extension
  996.  
  997.                 DelPtr    = strchr(ExtPtr, '|');
  998.                 ExtLen    = DelPtr - ExtPtr;
  999.  
  1000.                 if(!strnicmp(&MC->mc_FileName[strlen(MC->mc_FileName) - ExtLen], ExtPtr, ExtLen))
  1001.                     FoundDVI    = TRUE;
  1002.  
  1003.                 ExtPtr++;
  1004.             }
  1005.  
  1006.             if(FoundDVI)
  1007.                 strcpy(MC->mc_SearchName, MC->mc_ViewCmdDVI);
  1008.  
  1009.         }
  1010.  
  1011.  
  1012.             // No AmigaGuide, nor DVI file found, use default viewer
  1013.  
  1014.         if(!FoundAG && !FoundDVI)
  1015.             strcpy(MC->mc_SearchName, MC->mc_ViewCmd);
  1016.     }
  1017.     else
  1018.     {
  1019.             // Only use default viewer for non-extension files, when not set to "none"
  1020.  
  1021.         if(Stricmp(MC->mc_NonExt, "none"))
  1022.         {
  1023.                 // No extension use default viewer
  1024.  
  1025.             strcpy(MC->mc_SearchName, MC->mc_NonExt);
  1026.  
  1027.         }
  1028.     }
  1029.  
  1030.     MC->mc_Found = TRUE;
  1031.  
  1032.         // Append directory and FileName
  1033.  
  1034.     AddPart(MC->mc_CheckDir, MC->mc_FileName, 1024);
  1035.  
  1036.     strcat(MC->mc_SearchName, " ");
  1037.     strcat(MC->mc_SearchName, MC->mc_CheckDir);
  1038. }
  1039.